<script lang="ts" setup>
    import { reactive, ref, onMounted } from "vue";
    import { Ref, Reactive } from "@vue/reactivity";
    import { sendMessage, localSave, localStorage } from "@/utils/api"
    import {RefreshRight,} from '@element-plus/icons-vue'
    import alert from '@/components/alert.vue'
    const state = reactive({
        ttsRunning: false,
        voicesRunning: false,
    })
    const alertRef = ref(null)
    const audioRef = ref(null)
    const voiceParams = reactive({
        locale: "zh-CN",
        gender: "Female",
    })
    const ttsParams = reactive({
        t: '', // r 要转换的文本（需要进行URL编码）
        v: 'zh-CN-XiaoxiaoNeural', // short_name格式，默认: zh-CN-XiaoxiaoNeural
        r: 0, // 语速调整，范围: -100%到100%，默认: 0
        p: 0, // 语调调整，范围: -100%到100%，默认: 0
        o: '', // 输出音频格式，默认: audio-24khz-48kbitrate-mono-mp3
        s: '', // 情感风格，可用值取决于所选语音的style_list属性。例如："cheerful"、"sad"等
    })
    const voice = reactive({})
    const voices : Reactive<any[]> = reactive([
        {
        "name": "Microsoft Server Speech Text to Speech Voice (zh-CN, XiaoxiaoNeural)",
        "display_name": "Xiaoxiao",
        "local_name": "晓晓",
        "short_name": "zh-CN-XiaoxiaoNeural",
        "gender": "Female",
        "locale": "zh-CN",
        "locale_name": "Chinese (Mandarin, Simplified)",
        "style_list": [
            "assistant",
            "chat",
            "customerservice",
            "newscast",
            "affectionate",
            "angry",
            "calm",
            "cheerful",
            "disgruntled",
            "fearful",
            "gentle",
            "lyrical",
            "sad",
            "serious",
            "poetry-reading",
            "friendly",
            "chat-casual",
            "whispering",
            "sorry",
            "excited"
        ],
        "sample_rate_hertz": "48000"
    }
    ])
    
    onMounted(async () => {
        const {config} = await localStorage().get(["config"])
        if (config) {
            if (config.voices) {
                voices.splice(0, voices.length, ...config.voices)
            }
        }
        Object.assign(voice, voices[0])
    })
    watch(voices, async (newVal) => {
        Object.assign(voice, voices[0])
    })
    watch(()=>ttsParams.v, async (newVal) => {
        console.log(newVal)
        Object.assign(voice, voices.filter(v => v.short_name == newVal)[0])
        // ttsParams.s = voice.style_list[0]
    })
    const getVoices = async () => {
        state.voicesRunning = true
        const resp = await sendMessage({ action: 'voices', params: voiceParams });
        if (!resp.voices) return 
        voices.splice(0, voices.length, ...resp.voices)
        const config = await localStorage().get("config")
        if (config) {
            if (!config.voices) {
                config.voices = []
            }
            config.voices.splice(0, config.voices.length, ...voices)
            localSave("config", config)
        }
        console.log(voices)
        state.voicesRunning = false

    }
    const tts = async () => {
        if (!alertRef.value) return
        if (!ttsParams.t) {
            alertRef.value.warning("请输入文字")
            return
        }
        state.ttsRunning = true
        console.log(ttsParams)
        stream(`https://t.leftsite.cn/tts`, ttsParams).then(data=>{
            if (!audioRef.value) return
            // 创建一个 URL 对象，并绑定到 <audio> 标签的 src 属性
                // const audioURL = URL.createObjectURL(data as Blob);
                audioRef.value.src = URL.createObjectURL(data)
                audioRef.value.play()
                return {data}
            })
            .catch(error => {
                console.log({error})
            })
            .finally(()=>{
                state.ttsRunning = false
            })
    }
    
    const stream = (url: string, params: any=null, headers={}) => {
        return new Promise((resolve, reject) => {
            // 使用 URLSearchParams 对象构建查询字符串
            if (params) {
                url += '?' + new URLSearchParams(params).toString()
            }
            fetch(url, { mode: 'cors', headers})
                .then(response => resolve(response.blob()))
                .catch(error => {
                    // 处理错误
                    console.error(error);
                    alertRef.value.error("请求错误: ", error)
                    reject(error)
                });
        })
    }
</script>

<template>
  <div>
      <alert ref="alertRef"/>
    <el-row :gutter="20">
        <el-col :span="20">
          <el-input
              v-model="ttsParams.t"
              :rows="4"
              type="textarea"
              placeholder="Please input"
            />
        </el-col>
        <el-col :span="4">
          <el-button class="send" type="primary" plain @click="tts" :loading="state.ttsRunning">发送</el-button>
        </el-col>
    </el-row>
    <el-row :gutter="20">
        <el-col :span="6">
            <el-select v-model="ttsParams.v" placeholder="语音">
              <el-option v-for="item, i in voices" :key="i" :label="item.local_name" :value="item.short_name" />
            </el-select>
        </el-col>
        <el-col :span="6">
            <el-button :icon="RefreshRight" @click="getVoices" circle :loading="state.voicesRunning"/>
        </el-col>
        <el-col :span="6">
            <el-select v-model="voiceParams.locale" placeholder="语言">
              <el-option label="中文" value="zh-CN"/>
              <el-option label="英文" value="en-US"/>
            </el-select>
        </el-col>
        <el-col :span="4">
            <el-switch v-model="voiceParams.gender" active-value="Male" inactive-value="Female"
                inline-prompt
                style="--el-switch-on-color: #13ceff; --el-switch-off-color: #f7a898"
                active-text="男"
                inactive-text="女">
            </el-switch>
        </el-col>
    </el-row>
    <el-row :gutter="20">
        <el-col :span="6">
            <el-select v-model="ttsParams.s" placeholder="语气">
              <el-option v-for="item in voice.style_list" :key="item.name" :label="item.local_name" :value="item"/>
            </el-select>
        </el-col>
        <el-col :span="8">
            <span class="demonstration">语速</span>
            <el-slider v-model="ttsParams.r" :min="-100" :max="100" :step="1" size="small"/>
        </el-col>
        <el-col :span="8">
            <span class="demonstration">语调</span>
            <el-slider v-model="ttsParams.p" :min="-100" :max="100" :step="1" size="small"/>
        </el-col>
    </el-row>
    <el-row>
        <el-col :span="24">
          <audio ref="audioRef" controls></audio>
        </el-col>
    </el-row>
  </div>
</template>

<style scoped>
    .el-row {
      margin-bottom: 20px;
    }
    .send {
        height: 100%;
    }
</style>
